<?php

/*
 * Shortcut to using preg_match and then parsing $matches.  Returns the
 * result in $matches, less the first element, which is the whole string.
 *
 */
function preg_extract($pattern, $subject, $flags=null, $offset=null) {
	$result = preg_match($pattern, $subject, $matches, $flags, $offset);
	if (isset($matches) and is_array($matches)) {
		array_shift($matches);
		return $matches;
	}
	return false;
}

/*
 * Same as above function but using preg_match_all.
 *
 */
function preg_extract_all($pattern, $subject, $flags=null, $offset=null) {
	$result = preg_match_all($pattern, $subject, $matches, $flags, $offset);
	if (isset($matches) and is_array($matches)) {
		array_shift($matches);
		return $matches;
	}
	return false;
}

/*
 * array_index - Reindex an array of arrays, using a value of the 
 * sub array as the key.
 * 
 * array array_index ( array $array, string $key )
 *
 */
function array_index($array, $key) {
	if (!is_array($array)) return false;
	$new_array = array();
	foreach ($array as $element) {
		$new_array[$element[$key]] = $element;
	}
	return $new_array;
}

/*
 * array_value_at - direct equivalent of just $array[$index], the
 * benefit being you can use it with functions that return arrays
 * without having to assign it to a variable first.
 * 
 * mixed array_value_at( array $array, int $index )
 *
 */
function array_value_at($array, $index) {
	return isset($array[$index]) ? $array[$index] : null;
}

/*
 * human_filesize - Take a size in bytes, and return a human
 * readable version.
 * 
 * string human_filesize( int filesize )
 *
 */
function human_filesize($size) {
	$filesizename = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
	return round($size/pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i];
}

/*
 * famfamfam_icon - take a filename as input and output a 
 * suitable famfamfam icon.
 *
 */
function famfamfam_icon($filename) {
	$extension = strtolower(preg_replace('/^.*\./', '', $filename));
	$icons = array(
		'arw'  => 'camera',
		'cr2'  => 'camera',
		'dmg'  => 'cd',
		'dng'  => 'camera',
		'doc'  => 'page_white_word',
		'docx' => 'page_white_word',
		'gif'  => 'photo',
		'iso'  => 'cd',
		'jpeg' => 'photo',
		'jpg'  => 'photo',
		'pdf'  => 'page_white_acrobat',
		'php'  => 'page_white_php',
		'png'  => 'photo',
		'psd'  => 'picture',
		'rb'   => 'page_white_ruby',
		'txt'  => 'page_white_text',
		'xls'  => 'page_white_excel',
		'xlsx' => 'page_white_excel',
		'zip'  => 'photo'
	);
	if ($icons[$extension]) return $icons[$extension];
	else return 'page_white';

}

/*
 * highlight - take a haystack and needle, and wrap
 * instances of needle in <span class="hl"></span>
 *
 */
function highlight($haystack, $needle) {
	if ($needle) return preg_replace("/(".$needle.")/i", "<span class='hl'>$1</span>", $haystack);
	else return $haystack;
}

/*
 * make_path - take any string, and turn it into one suitable
 * to be used in a url
 *
 */
require 'chinese_to_pinyin.php';
require 'cyrillic_to_roman.php';
function make_path($string) {
	// convert chinese text to pinyin - this will need further processing
	// as it will contain accents.
	$string = chinese_to_pinyin($string);
	
	// convert cyrillic (russian, etc) to roman
	$string = cyrillic_to_roman($string);
	
	// deal with letters with accents
	$accents = array(
		'À' => 'a', 'Á' => 'a', 'Â' => 'a', 'Ã' => 'a', 'Ä' => 'a', 'Å' => 'a', 
		'Æ' => 'a', 'Ç' => 'c', 'È' => 'e', 'É' => 'e', 'Ê' => 'e', 'Ë' => 'e', 
		'Ì' => 'i', 'Í' => 'i', 'Î' => 'i', 'Ï' => 'i', 'Ð' => 'd', 'Ñ' => 'n', 
		'Ò' => 'o', 'Ó' => 'o', 'Ô' => 'o', 'Õ' => 'o', 'Ö' => 'o', 'Ø' => 'o', 
		'Ù' => 'u', 'Ú' => 'u', 'Û' => 'u', 'Ü' => 'u', 'Ý' => 'y', 'Þ' => 'b', 
		'ß' => 's', 'à' => 'a', 'á' => 'a', 'â' => 'a', 'ã' => 'a', 'ä' => 'a', 
		'å' => 'a', 'æ' => 'a', 'ç' => 'c', 'è' => 'e', 'é' => 'e', 'ê' => 'e', 
		'ë' => 'e', 'ì' => 'i', 'í' => 'i', 'î' => 'i', 'ï' => 'i', 'ð' => 'd', 
		'ñ' => 'n', 'ò' => 'o', 'ó' => 'o', 'ô' => 'o', 'õ' => 'o', 'ö' => 'o', 
		'ø' => 'o', 'ù' => 'u', 'ú' => 'u', 'û' => 'u', 'ý' => 'y', 'ý' => 'y', 
		'þ' => 'b', 'ÿ' => 'y', 'Ŕ' => 'R', 'ŕ' => 'r', 'ā' => 'a', 'ī' => 'i', 
		'ž' => 'z', 'ž' => 'z', 'č' => 'c', 'č' => 'c', 'š' => 's', 'š' => 's', 
		'è' => 'e', 'è' => 'e', 'ě' => 'e', 'ě' => 'e', 'ô' => 'o', 'ǫ' => 'o', 
		'ę' => 'e', 'ü' => 'u'
	);
	foreach($accents as $k => $v) {
		$string = str_replace($k, $v, $string);
	}
	
	// lowercase
	$string = strtolower($string);
	
	// replace & character with "and"
	$string = str_replace('&', "and", $string);
	
	// replace spaces with -
	$string = preg_replace("/ /", "-", $string);
	
	// strip out anything that isn't an acceptable character
	$string = preg_replace('/[^a-z0-9-_]/', '', $string);
	
	// get rid of any hyphen at the start/end
	$string = trim($string, '-');
	
	// multiple hyphens together should be single
	$string = preg_replace('/-+/', '-', $string);
	
	// and return.
	return $string;
	
}

/*
 * array_flatten - given an array of arrays, reduce to a single 
 * array containing all values.
 *
 */
function array_flatten($array) {
	$array_found = false;
	$array = array_values($array);
	for($i=0;$i<count($array);$i++) {
		if (is_array($array[$i])) {
			$array = array_merge(
				array_slice($array, 0, $i),
				array_flatten($array[$i]),
				array_slice($array, $i+1)
			);
			$array_found = true;
			break;
		}
	}

	if ($array_found) return array_flatten($array);
	return $array;
}

/*
 * Get the last query details from the zend profiler, and reconstruct 
 * the SQL it used.
 *
 */
function zend_db_last_query() {
	global $db;
	$prof = $db->getProfiler()->getLastQueryProfile();
	$query  = $prof->getQuery();
	$params = $prof->getQueryParams();
	foreach($params as $param) {
		if (is_numeric($param)) {
			$query = preg_replace('/\?/', $param, $query, 1);
		} else {
			$query = preg_replace('/\?/', "'" . addslashes($param) . "'", $query, 1);
		}
	}
	return $query;
}

/*
 * 
 *
 */
function parse_plugin($file, $configured) {
	global $app_root;
	$detail       = array('file' => substr($file, strlen($app_root)));
	$file_content = file_get_contents($file);
	$matches      = preg_extract('/^<\?php\n(\/\*.*?)\*\//s', $file_content);
	$lines        = preg_split("/[\n\r]/", $matches[0]);
	$config       = array();
	foreach($lines as $line) {
		$line = preg_replace('/^.*\* */', '', $line);
		$item = preg_split('/ *: */', $line, 2);
		if (isset($item[0]) and isset($item[1])) $detail[$item[0]] = $item[1];
	}
	if ($detail['enabled'] = isset($configured[$detail['file']])) {
		$detail['config'] = $configured[$detail['file']]['config'];
		if (isset($configured[$detail['file']]['manage_path'])) $detail['manage_path'] = $configured[$detail['file']]['manage_path'];
	}
	return $detail;
}

/*
 * Attempt to parse config as YAML and fall back to
 * old format if it fails.
 *
 */
function parse_config($config) {
	if (!$config) return array();
	try {
		include_once 'Yaml/sfYamlParser.php';
		$sfYamlParser = new sfYamlParser();
		$config = $sfYamlParser->parse($config);
		if (is_array($config)) return $config;
		return array();
	} catch (InvalidArgumentException $e) {
		$config = explode("\n", trim($config));
		$config_cpl = array();
		for($i=0;$i<count($config);$i++) {
			@list($key, $value) = preg_split("/ *= */", $config[$i], 2);
			$key = trim($key);
			if ($key == '>>>') {
				unset($append);
			} elseif($key == '}') {
				unset($array);
			} elseif (isset($append)) {
				$config_cpl[$append] .= $key . "\n";
			} elseif(isset($array) and $key == '[') {
				$array[] = array();
			} elseif(isset($array) and $key == ']') {
			} elseif (isset($array)) {
				$array[count($array)-1][$key] = $value;
			} elseif ($value == '<<<') {
				$config_cpl[$key] = '';
				$append = $key;
			} elseif ($value == '{') {
				$config_cpl[$key] = array();
				$array = &$config_cpl[$key];
			} else {
				$config_cpl[$key] = $value;
			}
		}
		return $config_cpl;
	}
}

/*
 * Get a unique reference. provide $reference and
 * return an incremented counter.
 *
 */
function uniqueref($reference) {
	global $db;
	$rows_affected = $db->update('cms_uniqueref', array('counter' => new Zend_Db_Expr('counter + 1')), $db->quoteInto('reference=?', $reference));
	if ($rows_affected) {
		return $db->fetchOne("SELECT counter FROM cms_uniqueref WHERE reference=?", $reference);
	} else {
		$db->insert('cms_uniqueref', array('reference' => $reference, 'counter' => 1));
		return 1;
	}
}

/*
 * Return first non-null value
 *
 */
function coalesce() {
	$args = func_get_args();
	foreach($args as $arg) {
		if ($arg !== null and $arg !== array()) return $arg;
	}
	return null;
}

/*
 * Numeric comparison
 * 
 */
function numcmp($a, $b) {
	if ($a == $b) return 0;
	return $a > $b ? 1 : 0;
}

/*
 * Check for an ajax request
 *
 */
function is_xhr() {
	return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) and $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');
}

/*
 * Get full path to a page given page id
 *
 */
 function get_page_path($id) {
	global $db;
	$path = array();
	while($id) {
		$page = $db->fetchRow("SELECT parent_id, path FROM site_pages p JOIN site_pages_revisions r ON p.revision_id=r.id WHERE p.id=?", $id);
		$path[] = $page['path'];
		$id = $page['parent_id'];
	}
	array_pop($path);
	$path = join('/', array_reverse($path)) . '/';
	if ($path != '/') $path = '/' . $path;
	return $path;
}

/*
 * array_rotate
 *
 */
function array_rotate($array) {
	$new_array = array();
	foreach ($array as $el) {
		foreach($el as $i => $value) {
			if (!isset($new_array[$i])) $new_array[$i] = array();
			$new_array[$i][] = $value;
		}
	}
	return $new_array;
}

function cloudfiles_insert($local, $data) {
	global $db, $env, $site;
	require_once 'CloudFiles/cloudfiles.php';
	
	$auth = new CF_Authentication($env['cdn']['cloudfiles']['username'], $env['cdn']['cloudfiles']['apikey']);
	$auth->ssl_use_cabundle();
	$auth->authenticate();

	$conn = new CF_Connection($auth);
	$conn->ssl_use_cabundle();
	
	$container = $conn->create_container("{$site['domain_name']}-images");
	$uri = $container->make_public();
	
	$cdnfile = trim(preg_replace('/[\/:]/', '-', $local), '-');
	
	$file = $container->create_object($cdnfile);
	$file->write($data);
	
	$db->insert('cms_cdn_mapping', array(
		'site_id' => $site['id'],
		'local'   => $local,
		'cdn'     => $uri . '/' . $cdnfile
	));
	
}


function ordinal($number) {
	if ($number >= 4 and $number <=20) return 'th';
	switch (substr($number, -1)) {
		case '1':
			return 'st';
		case '2':
			return 'nd';
		case '3':
			return 'rd';
		default:
			return 'th';
	}
}

/*
 * Smarty style escape
 *
 */
function escape($string, $esc_type = 'html')
{
    switch ($esc_type) {
        case 'html':
            return htmlspecialchars($string, ENT_QUOTES);

        case 'htmlall':
            return htmlentities($string, ENT_QUOTES);

        case 'url':
            return rawurlencode($string);

        case 'quotes':
            // escape unescaped single quotes
            return preg_replace("%(?<!\\\\)'%", "\\'", $string);

        case 'hex':
            // escape every character into hex
            $return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $return .= '%' . bin2hex($string[$x]);
            }
            return $return;
            
        case 'hexentity':
            $return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $return .= '&#x' . bin2hex($string[$x]) . ';';
            }
            return $return;

        case 'decentity':
            $return = '';
            for ($x=0; $x < strlen($string); $x++) {
                $return .= '&#' . ord($string[$x]) . ';';
            }
            return $return;

        case 'javascript':
            // escape quotes and backslashes, newlines, etc.
            return strtr($string, array('\\'=>'\\\\',"'"=>"\\'",'"'=>'\\"',"\r"=>'\\r',"\n"=>'\\n','</'=>'<\/'));
            
        case 'mail':
            // safe way to display e-mail address on a web page
            return str_replace(array('@', '.'),array(' [AT] ', ' [DOT] '), $string);
            
        case 'nonstd':
           // escape non-standard chars, such as ms document quotes
           $_res = '';
           for($_i = 0, $_len = strlen($string); $_i < $_len; $_i++) {
               $_ord = ord($string{$_i});
               // non-standard char, escape it
               if($_ord >= 126){
                   $_res .= '&#' . $_ord . ';';
               }
               else {
                   $_res .= $string{$_i};
               }
           }
           return $_res;

        default:
            return $string;
    }
}
